﻿/*
 * Created by SharpDevelop.
 * User: ley
 * Date: 5/16/2010
 * Time: 8:55 PM
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Collections.Generic;

namespace Ley.Common.Validation
{
	public class ValidationRuleSet<TSubject, TProperty> : IValidationRuleSet<TSubject>
	{
		private TProperty _target;
		private readonly SortedList<int, ValidationRule<TProperty>> _rules;
		
		public int RuleCount
		{
			get
			{
				return _rules.Count;
			}
		}
		
		public Validator<TSubject> Validator { get; set; }
		
		public ValidationRuleSet(Validator<TSubject> validator, Expression<Func<TSubject, TProperty>> subjectProperty)
		{
			_rules = new SortedList<int, ValidationRule<TProperty>>();
			
			Validator = validator;
			var getTargetFrom = subjectProperty.Compile();
			
			_target = getTargetFrom(Validator.Subject);
		}
		
		public ValidationRuleSet<TSubject, TTarget> Check<TTarget>(Expression<Func<TSubject, TTarget>> propertyRule)
		{
			return this.Validator.Check<TTarget>(propertyRule);
		}
		
		public ValidationResult PerformValidation()
		{
			return this.Validator.PerformValidation();
		}
		
		public ValidationRuleSet<TSubject, TProperty> Satisfies(Func<TProperty, bool> predicate, string message)
		{
			_rules.Add(_rules.Count, new ValidationRule<TProperty>(_target, predicate, message));
			return this;
		}
		
		public string Execute()
		{
			//need to execute rules the way it was configured FIFO style.
			for (int ruleIndex = 0; ruleIndex < _rules.Count; ruleIndex++)
			{
				var rule = _rules[ruleIndex];
				var message = rule.ExecuteRule();
				
				if (!string.IsNullOrEmpty(message))
					return message;
			}
			
			return string.Empty;
		}
	}
}
